<?php
namespace App\Http\Controllers\Front;

use App\Service\Front\PayService;
use Illuminate\Http\Request;

class PayWxController1115 extends BaseController
{
    //支付

    //必须的参数
    protected $app_id = 'wx8ead28aa79ce8683'; //appid
    protected $mch_id = '1691588547'; //商户号
    protected $key = 'karcvn1113mj1yfysww0dzcnbic4ec8r'; //秘钥
    protected $notify_url = ''; //通知接口
    //微信证书序列号：4A730B76F65D8C40C82BB1DB4B288D07E3B180BE

    public function __construct(PayService $service)
    {
        $this->db = $service;
        $this->notify_url = env('DOMAIN') . '/api/front/pay/wx/notice';
    }

    //PC微信支付
    public function pay(Request $request)
    {
        $token = $request->post('token', ''); //登录token
        $type = $request->post('type', 1); //1原创需求订单
        $orderno = $request->post('orderno', 0); //订单号
        $price = $this->db->orderPrice($type, $orderno);
        if (!$price) {
            return $this->toJson(-2, '价格错误');
        }
        $uOne = $this->db->userByToken($token);
        if (!$uOne) {
            return $this->toJson(-2, '未登录');
        }
        //微信支付
        $timeStamp = time();
        $userIp = $this->getUserIp();
        $nonce = toOrderno();
        $config = array(
            'mch_id' => $this->mch_id,
            'appid' => $this->app_id,
            'key' => $this->key,
        );
        $unified = array(
            'appid' => $config['appid'],
            'attach' => 'pay',
            'body' => 'order',
            'mch_id' => $config['mch_id'],
            'nonce_str' => $nonce,
            'notify_url' => $this->notify_url,
            'out_trade_no' => $orderno,
            'spbill_create_ip' => $userIp,
            'total_fee' => $price,
            'trade_type' => 'NATIVE',
        );
        $unified['sign'] = $this->wxSign($unified, $this->key);
        $xml = $this->arr2Xml($unified);
        $httpUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $responseXml = $this->toCurl($httpUrl, $xml);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        ddd($unifiedOrder);
//        if ($unifiedOrder === false) {
//            die('parse xml error');
//        }
//        if ($unifiedOrder->return_code != 'SUCCESS') {
//            die($unifiedOrder->return_msg);
//        }
//        if ($unifiedOrder->result_code != 'SUCCESS') {
//            die($unifiedOrder->err_code);
//        }
//        $codeUrl = (array)($unifiedOrder->code_url);
//        if(!$codeUrl[0]) exit('get code_url error');
//        $arr = array(
//            "appId" => $config['appid'],
//            "timeStamp" => $timeStamp,
//            "nonceStr" => $nonce,
//            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
//            "signType" => 'MD5',
//            "code_url" => $codeUrl[0],
//        );
//        $arr['paySign'] = self::getSign($arr, $config['key']);
//        return $arr;
    }

//    //wx支付
//    public function wxPay(Request $request)
//    {
//        $token = $request->post('token', ''); //登录token
//        $type = $request->post('type', 1); //1原创需求订单
//        $orderno = $request->post('orderno', 0); //订单号
//        $price = $this->db->orderPrice($type, $orderno);
//        if (!$price) {
//            return $this->toJson(-2, '价格错误');
//        }
//        $uOne = $this->db->userByToken($token);
//        if (!$uOne) {
//            return $this->toJson(-2, '未登录');
//        }
//        $uid = $uOne['id'];
////        $openid = $uOne['openid'];
//        $userIp = $this->getUserIp();
//        $nonce = toOrderno();
//        $amount = $price;
//        //构建签名
//        $signs = [
//            'appid' => $this->app_id,
//            'mch_id' => $this->mch_id,
//            'nonce_str' => $nonce,
//            'body' => 'order',
//            'notify_url' => $this->notify_url,
//            'out_trade_no' => $orderno,
//            'spbill_create_ip' => $userIp,
//            'total_fee' => $amount,
//            'trade_type' => 'JSAPI',
//            'sign_type' => 'MD5',
////            'openid' => $openid,
//        ];
//        ksort($signs);
//        var_dump($signs); echo '<br>1';
//        $string = '';
//        foreach ($signs as $k => $v) {
//            if ($v) {
//                $string .= $k . '=' . $v . '&';
//            }
//        }
//        $string .= 'key=' . $this->key;
//        var_dump($string); echo '<br>2';
//        $payData = [
//            'uid' => $uid, 'from_type' => $type,
//            'out_trade_no' => $orderno, 'money' => $amount,
//            'order_sign' => $string,
//        ];
//        $lastid = $this->db->wxPayAdd($payData); //支付log
//        $signStr = strtoupper(md5($string));
//        var_dump($signStr); echo '<br>3';
//        //构建请求参数
//        $param = '';
//        $param .= '<xml>';
//        $param .= '<appid>' . $this->app_id . '</appid>';
//        $param .= '<body>order</body>';
//        $param .= '<mch_id>' . $this->mch_id . '</mch_id>';
//        $param .= '<nonce_str>' . $nonce . '</nonce_str>';
//        $param .= '<notify_url>' . $this->notify_url . '</notify_url>';
//        $param .= '<out_trade_no>' . $orderno . '</out_trade_no>';
//        $param .= '<spbill_create_ip>' . $userIp . '</spbill_create_ip>';
//        $param .= '<total_fee>' . $amount . '</total_fee>';
//        $param .= '<trade_type>JSAPI</trade_type>';
//        //$param .= '<openid>' . $openid . '</openid>';
//        $param .= '<sign_type>MD5</sign_type>';
//        $param .= '<sign>' . $signStr . '</sign>';
//        $param .= '</xml>';
//        var_dump($param); echo '<br>4';
//        $this->db->wxPayModify($lastid, ['order_req'=>$param]);
//        $httpUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
//        $res = $this->toCurl($httpUrl, $param, 1);
//        var_dump($res); echo '<br>5';
//        $payData = [
//            'order_back' => json_encode($res, JSON_UNESCAPED_UNICODE),
//        ];
//        $this->db->wxPayModify($lastid, $payData); //支付log
//        if ($res['code'] < 0) {
//            return $this->toJson(-2, $res['msg']);
//        }
//        //用于唤起的参数
//        $resData = [
//            'appId' => $this->app_id,
//            'timeStamp' => (string) time(),
//            'nonceStr' => toOrderno(),
//            'package' => 'prepay_id=' . $res['data']['prepay_id'],
//            'signType' => 'MD5',
//        ];
//        ksort($resData);
//        $string = '';
//        foreach ($resData as $k => $v) {
//            if ($v) {
//                $string .= $k . '=' . $v . '&';
//            }
//        }
//        $string .= 'key=' . $this->key;
//        $resData['mchId'] = $this->mch_id;
//        $resData['orderInfo'] = $type==1 ? 'recharge' : 'order';
//        $resData['key'] = $this->key;
//        $resData['paySign'] = strtoupper(md5($string));
//        $payData = [
//            'pay_info' => json_encode($resData, JSON_UNESCAPED_UNICODE),
//            'status' => 1,
//        ];
//        $this->db->wxPayModify($lastid, $payData); //支付log
//        return $this->toJson(0, '', $resData);
//    }

    //微信通知
    public function notice()
    {
        $xml = file_get_contents('php://input');
        $lastid = $this->db->wxNotice($xml);
        $prefix = '<![CDATA['; $suffix = ']]>';
        //return_code
        $res = preg_match('/<return_code>(.*?)<\/return_code>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'return_code 缺失');
        }
        $return_code = $matches[1];
        if (substr($return_code, 0, strlen($prefix)) == $prefix) {
            $return_code = substr($return_code, 9);
        }
        if (substr($return_code, -3) == $suffix) {
            $return_code = substr($return_code, 0, -3);
        }
        if ($return_code != 'SUCCESS') {
            return $this->toJson(-2, '通信失败');
        }
        $items['return_code'] = $return_code;
        //result_code
        $res = preg_match('/<result_code>(.*?)<\/result_code>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'result_code 缺失');
        }
        $result_code = $matches[1];
        if (substr($result_code, 0, strlen($prefix)) == $prefix) {
            $result_code = substr($result_code, 9);
        }
        if (substr($result_code, -3) == $suffix) {
            $result_code = substr($result_code, 0, -3);
        }
        if ($result_code != 'SUCCESS') {
            return $this->toJson(-2, '交易失败');
        }
        $items['result_code'] = $return_code;
        //out_trade_no
        $res = preg_match('/<out_trade_no>(.*?)<\/out_trade_no>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'out_trade_no 缺失');
        }
        $out_trade_no = $matches[1];
        if (substr($out_trade_no, 0, strlen($prefix)) == $prefix) {
            $out_trade_no = substr($out_trade_no, 9);
        }
        if (substr($out_trade_no, -3) == $suffix) {
            $out_trade_no = substr($out_trade_no, 0, -3);
        }
        $items['out_trade_no'] = $out_trade_no;
        $this->db->wxNoticeModify($lastid, $out_trade_no);
        return $this->toJson(0, '', $items);
    }

    /**
     * 构建CURL请求，单线程
     * @param string $httpUrl 请求地址
     * @param string $string 参数拼接的字符串
     * @return $json
     */
    public function toCurl($httpUrl = '', $string = '', $is_ddd = 0)
    {
        $curl = curl_init(); //初始化
        curl_setopt($curl,CURLOPT_URL,$httpUrl);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
        curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
        curl_setopt($curl, CURLOPT_ENCODING, '');
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $string);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($string),
            'Accept: application/json'
        ));
        curl_setopt($curl, CURLOPT_TIMEOUT, 5);
        $output = curl_exec($curl);
        curl_close($curl);
        ddd($output);
//        if ($is_ddd) ddd($output);
//        if (!$output) {
//            return array('code'=>-1, 'msg'=>'请求失败');
//        }
//        //$items = json_decode($output,true);
//        $items = $this->xml2arr($output);
//        if ($items['code'] < 0) {
//            return array('code' => -2,'msg' => 'XML解析错误', 'data' => $items);
//        }
//        return array('code' => 0,'msg' => 'success', 'data' => $items['data']);
    }

    //解析xml
    public function xml2arr($xml)
    {
        $items = [];
        ////////////////////////正则匹配
        $prefix = '<![CDATA['; $suffix = ']]>';
        //return_code
        $res = preg_match('/<return_code>(.*?)<\/return_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'return_code 缺失', 'data' => $xml);
        }
        $return_code = $matches[1];
        if (substr($return_code, 0, strlen($prefix)) == $prefix) {
            $return_code = substr($return_code, 9);
        }
        if (substr($return_code, -3) == $suffix) {
            $return_code = substr($return_code, 0, -3);
        }
        $items['return_code'] = $return_code;
        //result_code
        $res = preg_match('/<result_code>(.*?)<\/result_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'result_code 缺失', 'data' => $xml);
        }
        $result_code = $matches[1];
        if (substr($result_code, 0, strlen($prefix)) == $prefix) {
            $result_code = substr($result_code, 9);
        }
        if (substr($result_code, -3) == $suffix) {
            $result_code = substr($result_code, 0, -3);
        }
        $items['result_code'] = $result_code;
        //prepay_id
        $res = preg_match('/<prepay_id>(.*?)<\/prepay_id>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'prepay_id 缺失', 'data' => $xml);
        }
        $prepay_id = $matches[1];
        if (substr($prepay_id, 0, strlen($prefix)) == $prefix) {
            $prepay_id = substr($prepay_id, 9);
        }
        if (substr($prepay_id, -3) == $suffix) {
            $prepay_id = substr($prepay_id, 0, -3);
        }
        $items['prepay_id'] = $prepay_id;
        //return_msg
        $res = preg_match('/<return_msg>(.*?)<\/return_msg>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'prepay_id 缺失', 'data' => $xml);
        }
        $return_msg = $matches[1];
        if (substr($return_msg, 0, strlen($prefix)) == $prefix) {
            $return_msg = substr($return_msg, 9);
        }
        if (substr($return_msg, -3) == $suffix) {
            $return_msg = substr($return_msg, 0, -3);
        }
        $items['return_msg'] = $return_msg;
        //判断错误
        if ($return_code != 'SUCCESS' || $result_code != 'SUCCESS') {
            return array('code' => -2, 'msg' => $return_msg, 'data' => $xml);
        }
        return array('code' => 0, 'msg' => 'success', 'data' => $items);
    }

    //数组转xml
    public function arr2Xml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * 获取签名
     */
    public function wxSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }

    public function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
}